import uuid
from typing import Union

from agent import CentralBank, HouseHolds, Banks, Firms, Government
from utils import Record

def trade_from_deposit_to_deposit(
    amount: Union[float, int],
    item: str,
    payer: Union[Firms, HouseHolds],
    payee: Union[Firms, HouseHolds],
    payer_bank: Banks,
    payee_bank: Banks,
    transaction_flow_item: str
    ):
    """
    存款对存款的交易
    用于
    # 11. Consumption goods market
    # 15.2 firm_pay_dividends
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'payer_bank': payer_bank.id_(),
        'payee_bank': payee_bank.id_(),
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }
    # 这里record要分支
    payer.pay(
        money=amount, 
        record=Record(uuid.uuid4()).set_more_attr(record_dic)
        )
    payee.accept_payment(
        money=amount, 
        record=Record(uuid.uuid4()).set_more_attr(record_dic)
        )
    # 如果是同一个银行，那么就不进行银行账户的变动
    if payer_bank.bank_id == payee_bank.bank_id:
        payer_bank.pay(
            money=0, 
            record=Record(uuid.uuid4()).set_more_attr(record_dic)
            )
    else:
        payer_bank.pay(
            money=amount, 
            record=Record(uuid.uuid4()).set_more_attr(record_dic)
            )
        payee_bank.accept_payment(
            money=amount, 
            record=Record(uuid.uuid4()).set_more_attr(record_dic)
            )


def trade_from_deposit_to_reserve(
    amount: Union[float, int],
    item: str,
    payer: Union[HouseHolds, Firms],
    payee: Banks,
    payer_bank: Banks,
    transaction_flow_item: str
    ):
    """
    保证金对存款的交易，付款方为银行，银行保证金减少，收款方存款账户增加，收款方银行的保证金增加。
    当收款方银行就是付款方，其保证金先减少，后增加，或可以直接不变
    用于
    # 7 Credit Supply
    # 15.1 bank_pay_dividends
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'payer_bank': payer_bank.id_(),
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }
    payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    if payer_bank.bank_id == payee.bank_id:
        payer_bank.pay(money=0, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    else:
        payer_bank.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
        payee.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))


def trade_from_reserve_to_deposit(amount: Union[float, int], item: str, payer: Banks, payee: Union[Firms, HouseHolds],
                                  payee_bank: Banks, transaction_flow_item: str):
    """
    银行贷款交易：
    保证金对存款的交易，付款方为银行，银行保证金减少，收款方存款账户增加，收款方银行的保证金增加。
    当收款方银行就是付款方，其保证金先减少，后增加，或可以直接不变
    用于
    # 7 Credit Supply
    # 15.1 bank_pay_dividends
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'payee_bank': payee_bank.id_(),
        'amount': amount,
        'item': item,
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }
    payee.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))

    # 如果付款银行和存款银行是一个，那么只需要在贷款者的存款账户上增加一个存款金额就可以了
    if payee_bank.bank_id == payer.bank_id:
        payer.pay(money=0, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    else:
        payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))  # 1
        payee_bank.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))  # 3  1，3相互抵消


def trade_from_treasury_deposit_to_reserve(
    amount: Union[float, int],
    item: str,
    payer: Government,
    payee: Banks,
    transaction_flow_item: str
    ):
    """
    财政存款到保证金
    用于
    12.1政府支付国债利息
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }
    payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payee.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))


def trade_from_treasury_deposit_to_central_bank(
        amount: Union[float, int], 
        item: str, 
        payer: Government,
        payee: CentralBank,
        transaction_flow_item: str
        ):
    """
    财政存款还给央行
    用于
    12.2政府支付国债利息到央行
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }
    payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payee.log.append(Record(uuid.uuid4()).set_more_attr(record_dic))


def trade_from_central_bank_to_treasury_deposit(
        amount: Union[float, int], 
        item: str,
        payer:CentralBank, 
        payee: Government,
        transaction_flow_item: str
        ):
    """
    央行给政府钱
    """
    record_dic = {
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }
    payee.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payer.log.append(Record(uuid.uuid4()).set_more_attr(record_dic))

def trade_from_central_bank_to_reserve(
        amount: Union[float, int], 
        item: str, 
        payee: Banks,
        transaction_flow_item: str):
    record_dic = {
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }
    # payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payee.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    

def trade_from_reserve_to_central_bank(
    amount: Union[float, int],
    item: str,
    payer: Banks,
    payee: CentralBank,
    transaction_flow_item: str
    ):
    """
    银行保证金还给央行
    用于
    12.3现金预借款利息偿还
    12.4现金预借款本金偿还
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }
    payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payee.log.append(Record(uuid.uuid4()).set_more_attr(record_dic))


def trade_from_reserve_to_reserve(
    amount: Union[float, int],
    item: str,
    payer: Banks,
    payee: Banks,
    transaction_flow_item: str
    ):
    """
    银行保证金还给央行
    用于
    保证金的交易，此时居民或企业的存款已经重新签订
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }
    record = Record(uuid.uuid4())
    record.add_more_attr(record_dic)
    if payer.bank_id == payee.bank_id:
        record.amount = 0
        payer.pay(money=0, record=record)
    else:
        payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
        payee.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))


def trade_from_treasury_deposit_to_deposit(
    amount: Union[float, int], 
    item: str, 
    payer: Government, 
    payee: HouseHolds,
    payee_bank: Banks, 
    transaction_flow_item: str
    ):
    """
    财政存款到居民存款
    用于
    13.3政府发工资
    13.4政府发救济金
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'payee_bank': payee_bank.id_(),
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }

    payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payee.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payee_bank.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))


def trade_from_deposit_to_treasury_deposit(
    amount: Union[float, int], 
    item: str, 
    payer: Union[Firms, HouseHolds],
    payee: Government, 
    payer_bank: Banks, 
    transaction_flow_item: str
    ):
    """
    财政存款到居民存款
    用于
    14.1居民交税
    14.2消费品企业交税
    14.3资本品企业交税
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'payer_bank': payer_bank.id_(),
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }

    payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payer_bank.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payee.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))


def trade_from_reserve_to_treasury_deposit(
    amount: Union[float, int],
    item: str,
    payer: Banks,
    payee: Government,
    transaction_flow_item: str
    ):
    """
    保证金到财政存款
    用于
    14.4银行交税给政府
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'amount': amount,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }

    payer.pay(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payee.accept_payment(money=amount, record=Record(uuid.uuid4()).set_more_attr(record_dic))


def trade_consumption_goods(
    quantity: Union[float, int],
    item: str,
    payer: HouseHolds,
    payee: Firms,
    transaction_flow_item: str
    ):
    """
    实物消费品交易
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'quantity': quantity,
        'item': item,  # 用于分类合并用
        'transaction_flow_item': transaction_flow_item,
        'flow': f"{payer.identity}获得消费品, {payee.identity}库存减少",
        'uuid': uuid.uuid4(),
    }
    payer.pay(money=0, record=Record(uuid.uuid4()).set_more_attr(record_dic))
    payee.sell(quantity=quantity, record=Record(uuid.uuid4()).set_more_attr(record_dic))


def trade_capital_goods(quantity: Union[float, int], item: str, payer: Firms, payee: Firms,
                        transaction_flow_item: str):
    """
    资本品交易
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'quantity': quantity,
        'item': item,
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }

    price = payee.price_and_recruit.price
    # 付款人支付资金，收款人支付资本品
    payer.buy_capital(
        quantity=quantity,
        record=Record(uuid.uuid4()).set_more_attr(record_dic),
        price=price)
    payee.sell(
        quantity=quantity,
        record=Record(uuid.uuid4()).set_more_attr(record_dic)
        )


def trade_from_ca_to_ka(amount: Union[float, int], payer: Union[Firms, Banks], payee: Union[Firms, Banks],
                        item: str, transaction_flow_item: str):
    """
    公司内部存留收益，从ca经常账户到ka资本账户
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'amount': amount,
        'item': item,
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }

    payer.pay(
        money=0,
        record=Record(uuid.uuid4()).set_more_attr(record_dic)
        )

def trade_from_ka_to_ca(amount: Union[float, int], payer: Union[Firms, Banks], payee: Union[Firms, Banks],
                        item: str, transaction_flow_item: str):
    """
    公司内部弥补亏损，从ka经常账户到ca资本账户
    """
    record_dic = {
        'payer': payer.id_(),
        'payer_idy': payer.identity,
        'payee': payee.id_(),
        'payee_idy': payee.identity,
        'amount': amount,
        'item': item,
        'transaction_flow_item': transaction_flow_item,
        'uuid': uuid.uuid4(),
    }

    payer.pay(
        money=0,
        record=Record(uuid.uuid4()).set_more_attr(record_dic)
        )